
// Auto set on page load...
$(document).ready(function() {
  jQuery('form.FancyForm').ValidateForm();
});

FormValidator = function() {
  
  var form_counter = 0;
  var forms = {};
  
  
  var validators = {
    Required : function(field, caption) {
      if(field.val() == '') {
        return 'Bạn chưa nhập ' + caption;
      } else {
        return true;
      }
    },
    
    ValidateMinLength : function(field, caption) {
      var min_length = 0;
      var classes = field.attr('class').split(' ');
      
      for(var i = 0; i < classes.length; i++) {
        if(classes[i] == 'ValidateMinLength') {
          if((classes[i + 1] != 'undefined') && !isNaN(classes[i + 1])) {
            min_length = parseInt(classes[i + 1]);
            break;
          } // if
        } // if
      } // for
      
      if((min_length > 0) && (field.val().length < min_length)) {
        return caption + ' tối thiểu phải chứa ' + min_length + ' ký tự.';
      } else {
        return true;
      } // if
    },
    
    ValidateMaxLength : function(field, caption) {
      var max_length = 0;
      var classes = field.attr('class').split(' ');
      
      for(var i = 0; i < classes.length; i++) {
        if(classes[i] == 'ValidateMaxLength') {
          if((classes[i + 1] != 'undefined') && !isNaN(classes[i + 1])) {
            max_length = parseInt(classes[i + 1]);
            break;
          } // if
        } // if
      } // for
      
      if((max_length > 0) && (field.val().length > max_length)) {
        return caption + ' chỉ chứa tối đa ' + max_length + ' ký tự.';
      } else {
        return true;
      } // if
    },
    
    ValidateSameAs : function(field, caption) {
      var classes = field.attr('class').split(' ');
      var target_field_name = '';
      
      for(var i = 0; i < classes.length; i++) {
        if(classes[i] == 'ValidateSameAs') {
          if(classes[i + 1] != 'undefined') {
            target_field_name = classes[i + 1];
            break;
          } // if
        } // if
      } // for
      
      if(target_field_name) {
        var target_field = jQuery('#' + target_field_name);
        if(target_field.length > 0) {
          var target_field_caption = field_caption(target_field);
          
          if(target_field.val() != field.val()) {
            return 'Giá trị của '+ caption + ' và ' + target_field_caption + ' không giống nhau.';
          } // if
        } // if
      } // if
      
      return true;
    },
    
    ValidateEmail : function(field, caption) {
      if(field.val().match(/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/)) {
        return true;
      } else {
        return 'Địa chỉ email không hợp lệ.';
      }
    },
    
    ValidateUrl : function(field, caption) {
      if(field.val().match(/^(http|https|ftp):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+)(:(\d+))?\/?/i)) {
        return true;
      } else {
        return 'URL không hợp lệ.';
      }
    }, 
    
    ValidateNumber : function(field, caption) {
      if(field.val().match(/(^-?\d\d*\.\d*$)|(^-?\d\d*$)|(^-?\.\d\d*$)/)) {
        return true;
      } else {
        return caption + ' không phải là số nguyên';
      }
    },
    
    ValidateInteger : function(field, caption) {
      if(field.val().match(/(^-?\d\d*$)/)) {
        return true;
      } else {
        return caption + ' không phải là số nguyên.';
      }
    },
    
    ValidateAlpha : function(field, caption) {
      if(field.val().match(/^[a-zA-Z]+$/)) {
        return true;
      } else {
        return caption + ' chỉ chứa các chữ cái (không chứa các ký tự đặc biệt hay số)';
      }
    },
    
    ValidateAlphaNum : function(field, caption) {
      if(field.val().match(/\W/)) {
        return caption + ' chỉ chứa các chữ cái và số (không chứa các ký tự đặc biệt)';
      } else {
        return true;
      }
    },
    
    ValidateCallback : function(field, caption) {
      var classes = field.attr('class').split(' ');
      var callback_function = '';
      
      for(var i = 0; i < classes.length; i++) {
        if(classes[i] == 'ValidateCallback') {
          if(classes[i + 1] != 'undefined') {
            callback_function = classes[i + 1];
            break;
          } // if
        } // if
      } // for
      
      if(window[callback_function] != 'undefined' && (typeof window[callback_function] == 'function')) {
        return window[callback_function](field, caption);
      } // if
      
      return 'Không thể kiểm tra giá trị của ' + caption + '. Hàm kiểm tra (' + callback_function + ') chưa được định nghĩa!';
    }
    
  };
  
  var validate_form = function(for_form, all_fields, is_submit) {
    var result = true;
    
    if(typeof(forms[for_form.attr('id')]['validation']) == 'object') {
      for(var field_name in forms[for_form.attr('id')]['validation']) {
      
        if(all_fields || forms[for_form.attr('id')]['focused_fields'][field_name]) {
          var field = forms[for_form.attr('id')]['validation'][field_name]['field'];
          var field_caption = forms[for_form.attr('id')]['validation'][field_name]['caption'];
          var field_validators = forms[for_form.attr('id')]['validation'][field_name]['validators'];
          
          for(var validator in field_validators) {
            var validation_result = validators[validator](field, field_caption, for_form);
        
            if(typeof(validation_result) == 'string') {
              set_field_error(field, validation_result, (is_submit?for_form:false));
              result = false;
              break;
            } else {
              remove_field_error(field);
            } // if
          } // for
        } // if
        
      }  // if
    } // if
    
    return result;
  };
  
  var set_field_error = function(for_field, error_message, for_form) {
    var holder = find_field_holder(for_field);
    if(holder === false) {
      return;
    } // if
    
    holder.removeClass('Error').find('p.ErrorField').remove();
    holder.addClass('Error').prepend('<p class="ErrorField" id="error_' + for_field.attr('id') + '"><strong>' + error_message + '</strong></p>');
    
    if(for_form) {
      for_form.find('#errorMsg').show();
      var errorMsgField = for_form.find('#errorMsg ol');
      errorMsgField.prepend('<li><a title="Jump to error" href="#error_'+for_field.attr('id')+'">'+error_message+'</a></li>');
    }
  };

  var remove_field_error = function(for_field) {
    var holder = find_field_holder(for_field);
    if(holder === false) {
      return;
    } // if
    holder.removeClass('Error').find('p.ErrorField').remove();
  };
  
  var find_field_holder = function(for_field) {
    var parent = for_field.parent();
      
    while(typeof(parent) == 'object') {
      if(parent[0].nodeName == 'FORM') {
        return;
      } // if
      if(parent[0].className.indexOf('CtrlHolder') >= 0) {
        return parent;
      } // if
      parent = jQuery(parent.parent());
    } // while
    
    return false;
  };
  
  var mark_as_focused = function(for_form, for_field) {
    if(typeof(forms[for_form.attr('id')]['focused_fields'][for_field.attr('name')]) == 'undefined') {
      forms[for_form.attr('id')]['focused_fields'][for_field.attr('name')] = true;
    } // if
    
    var holder = find_field_holder(for_field);
    if(typeof(holder) == 'object') {
      if(holder.attr('class').indexOf('Focused') == -1) {
        for_form.find('.' + 'Focused').removeClass('Focused');
        holder.addClass('Focused'); 
      } // if
    } // if
  };

  var field_caption = function(for_field) {
    var field_id = for_field.attr('id');
    if(field_id) {
      var label = jQuery('label[@for=' + field_id + ']');
      if(typeof(label) == 'object') {
        var text = label.text();
        if(text.substr(0, 1) == '*') {
          return text.substring(2);
        } else {
          return text;
        } // if
      } // if
    } // if
    return 'Field';
  };

  var get_form_id = function(for_form) {
    var form_id = for_form.attr('id');
      
    if(!form_id) {
      form_counter++;
      form_id = 'uniform_form_' + form_counter;
      for_form.attr('id', form_id);
    } // if
    
    return form_id;
  };
  
  return {
    
    init : function(form, settings) {
      var fields = form.find(settings.field_selector);
      var form_id = get_form_id(form);
      var errorMsgField = form.find('#errorMsg');
      
      // Register form
      forms[form_id] = {
        'form'           : form,
        'fields'         : fields,
        'settings'       : settings,
        'validation'     : {},
        'focused_fields' : {},
        'ok_to_submit'   : false
      };
      
      // Walk through defined validators and maku sure that they do their trick
      for(validator in validators) {
        form.find('.' + validator).each(function() {
          var field = $(this);
          var field_name = field.attr('name');
          
          if(typeof forms[form_id]['validation'][field_name] != 'object') {
            forms[form_id]['validation'][field_name] = {
              'field'      : field,
              'caption'    : field_caption(field),
              'validators' : {}
            };
          } // if
          
          forms[form_id]['validation'][field_name]['validators'][validator] = validators[validator];
        });
      } // for
      
      fields.focus(function() {
        mark_as_focused(form, $(this));
      }).blur(function() {
        validate_form(form, false);
      });
      
      // Form submission handler
      form.submit(function() {
        form.find('#errorMsg').hide();
        form.find('#errorMsg ol li').each(function(){
            $(this).remove();
        });
        var is_valid = validate_form(form, true, true);
        if(is_valid) {
          forms[form.attr('id')]['ok_to_submit'] = true;
          return true;
        } else {
          /*$('div.AjaxLoader').hide();*/
          return false;
        } // if
      });
    } // init
    
  };
  
}();

String.prototype.toInt = 
    function(){
        var result = parseInt(this, 10);
		return isNaN(result)?0:result;
	}

jQuery.fn.ValidateForm = function(settings) {
  settings = jQuery.extend({
    valid_class    : 'Valid',
    invalid_class  : 'Invalid',
    focused_class  : 'focused',
    holder_class   : 'ctrlHolder',
    field_selector : 'input, select, textarea'
  }, settings);
  
  return this.each(function() {
    FormValidator.init($(this), settings);
  });
  
} // ValidateForm